using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Projet_Synthese
{
    /// <summary>
    /// Type principal pour votre jeu
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        #region Champ
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        private Tangram tangram;
        private NUICursor cursor;
        private int selectionné = -1;
        private double auxtemps = 0;
        private double temps = 0;
        private SpriteFont spriteFont;
        private float Precision = 2;
        private DateTime tempsEcouler;
        private TimeSpan tempsPartie;
        private SoundEffect depot;
        private SoundEffect partieFinie;
        private Song ambiance;
        private Texture2D fond;
        private Rectangle destinationFond;
        private bool isPlaying = false;
        private KeyboardState oldKeyboardState;
        PartieManager partieManger;
        #endregion

        #region Constructeur
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Textures";
            cursor = new NUICursor(this);
        } 
        #endregion

        #region Initialisation
        /// <summary>
        /// Permet au jeu d’effectuer l’initialisation nécessaire pour l’exécution.
        /// Il peut faire appel aux services et charger tout contenu
        /// non graphique. Calling base.Initialize énumère les composants
        /// et les initialise.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Ajouter votre logique d’initialisation ici
            graphics.PreferredBackBufferHeight = GraphicsDevice.DisplayMode.Height;
            graphics.PreferredBackBufferWidth = GraphicsDevice.DisplayMode.Width;
            graphics.ApplyChanges();
            cursor.Initialize(GraphicsDevice.DisplayMode.Width-10, GraphicsDevice.DisplayMode.Height - 10);
            if (cursor.KinectSensor != null)
                Precision = 15;
            destinationFond = new Rectangle(0, 0, GraphicsDevice.DisplayMode.Width, graphics.PreferredBackBufferHeight);
            oldKeyboardState = Keyboard.GetState();
            partieManger = new PartieManager();
            base.Initialize();
        }

        /// <summary>
        /// LoadContent est appelé une fois par partie. Emplacement de chargement
        /// de tout votre contenu.
        /// </summary>
        protected override void LoadContent()
        {
            // Créer un SpriteBatch, qui peut être utilisé pour dessiner des textures.

            spriteBatch = new SpriteBatch(GraphicsDevice);
            Texture2D[] texture = new Texture2D[20];
            texture[0] = Content.Load<Texture2D>("Base/Carre");
            texture[1] = Content.Load<Texture2D>("Base/Parallelogramme");
            texture[2] = Content.Load<Texture2D>("Base/TriangleGrand");
            texture[3] = Content.Load<Texture2D>("Base/TriangleMoyen");
            texture[4] = Content.Load<Texture2D>("Base/TrianglePetit");
            texture[5] = Content.Load<Texture2D>("Base/CarreSelect");
            texture[6] = Content.Load<Texture2D>("Base/ParallelogrammeSelect");
            texture[7] = Content.Load<Texture2D>("Base/TriangleGrandSelect");
            texture[8] = Content.Load<Texture2D>("Base/TriangleMoyenSelect");
            texture[9] = Content.Load<Texture2D>("Base/TrianglePetitSelect");
            texture[10] = Content.Load<Texture2D>("Base/CarreVerrouille");
            texture[11] = Content.Load<Texture2D>("Base/ParallelogrammeVerrouille");
            texture[12] = Content.Load<Texture2D>("Base/TriangleGrandVerrouille");
            texture[13] = Content.Load<Texture2D>("Base/TriangleMoyenVerrouille");
            texture[14] = Content.Load<Texture2D>("Base/TrianglePetitVerrouille");
            texture[15] = Content.Load<Texture2D>("Base/CarrePlein");
            texture[16] = Content.Load<Texture2D>("Base/ParallelogrammePlein");
            texture[17] = Content.Load<Texture2D>("Base/TriangleGrandPlein");
            texture[18] = Content.Load<Texture2D>("Base/TriangleMoyenPlein");
            texture[19] = Content.Load<Texture2D>("Base/TrianglePetitPlein");

            for (int i = 1; i < 5; i++)
            {
                texture[(i * 5) - IdTexture.Carre].Tag = "Carre";
                texture[(i * 5) - IdTexture.Parallelogramme].Tag = "Parallelogramme";
                texture[(i * 5) - IdTexture.TriangleGrand].Tag = "TriangleGrand";
                texture[(i * 5) - IdTexture.TriangleMoyen].Tag = "TriangleMoyen";
                texture[(i * 5) - IdTexture.TrianglePetit].Tag = "TrianglePetit";
            }
            partieManger.Load("Tangram", texture);
            LoadContentPartie();

            if (cursor.KinectSensor != null)
            {
                cursor.LoadContent(Content);
                Partie.AngleRatation = 0.3f;
            }
            
            tempsEcouler = DateTime.Now.ToLocalTime();
            tempsPartie = DateTime.Now.Subtract(tempsEcouler);
            spriteFont = Content.Load<SpriteFont>("Base/SpriteFont1");
        } 
        #endregion

        /// <summary>
        /// UnloadContent est appelé une fois par partie. Emplacement de déchargement
        /// de tout votre contenu.
        /// </summary>
        protected override void UnloadContent()
        {
            if (cursor.KinectSensor != null)
                cursor.KinectSensor.Stop();
            // TODO: Déchargez le contenu non ContentManager ici
        }
        
        #region Controles
        private void ControleKinect(FormeGeometrique selection)
        {
            if (!cursor.EstSelectionnable)
            {
                selectionné = -1;
                if (selection != null)
                {
                    selection.EstSelectionné = false;
                    cursor.EstSelectionné = false;
                    selection = null;
                    depot.Play();
                }
            }
            else
            {
                if (selection == null)
                {

                    for (int i = 0; i < 7; i++)
                    {
                        if (tangram[i] != null && cursor.DestinationMainGauche.Intersects(tangram[i].RectangleDestination))
                        {
                            selectionné = i;
                            selection = tangram[i];
                            selection.EstSelectionné = true;
                            cursor.EstSelectionné = true;
                            depot.Play();
                            break;
                        }
                    }
                }
                else
                {
                    Point deplacement = new Point(selection.RectangleDestination.Center.X - cursor.DestinationMainGauche.Center.X, selection.RectangleDestination.Center.Y - cursor.DestinationMainGauche.Center.Y);
                    selection.RectangleDestination.X += deplacement.X * -1;
                    selection.RectangleDestination.Y += deplacement.Y * -1;
                    selection.RotationForme((float)cursor.SensRotation * Partie.AngleRatation);
                    if (selection.RectangleDestination.X > (graphics.PreferredBackBufferWidth - 10))
                        selection.RectangleDestination.X = (graphics.PreferredBackBufferWidth - 10);
                    else if (selection.RectangleDestination.X < 10)
                        selection.RectangleDestination.X = 10;
                    if (selection.RectangleDestination.Y > (graphics.PreferredBackBufferHeight-10))
                        selection.RectangleDestination.Y = (graphics.PreferredBackBufferHeight-10);
                    else if (selection.RectangleDestination.Y < 10)
                        selection.RectangleDestination.Y = 10;
                }
            }
        }
        private void LoadContentPartie()
        {
            MediaPlayer.Stop();
            if (partieManger.Partie.ImageFond == String.Empty)
                fond = Content.Load<Texture2D>("Defaut/fond");
            else fond = Content.Load<Texture2D>(partieManger.Partie.ImageFond);

            if (partieManger.Partie.EffetDeposé == String.Empty)
                depot = Content.Load<SoundEffect>("Defaut/depot");
            else depot = Content.Load<SoundEffect>(partieManger.Partie.EffetDeposé);

            if (partieManger.Partie.EffetTerminé == String.Empty)
                partieFinie = Content.Load<SoundEffect>("Defaut/partieFinie");
            else partieFinie = Content.Load<SoundEffect>(partieManger.Partie.EffetTerminé);

            if (partieManger.Partie.Ambiance == String.Empty)
                ambiance = Content.Load<Song>("Defaut/ambiance");
            else ambiance = Content.Load<Song>(partieManger.Partie.Ambiance);

            if (!partieManger.Partie.IsFinish)
                tangram = partieManger.Partie.Tangram;

            MediaPlayer.Play(ambiance);
            MediaPlayer.IsRepeating = true;
        }
        private void ControleClavier(FormeGeometrique selection, KeyboardState keyboardState)
        {
            if (selection != null)
            {
                selection.EstSelectionné = true;

                if (keyboardState.IsKeyDown(Keys.Q))
                    selection.RotationForme(- Partie.AngleRatation);
                if (keyboardState.IsKeyDown(Keys.D))
                    selection.RotationForme(Partie.AngleRatation);
                if (keyboardState.IsKeyDown(Keys.Right))
                    selection.RectangleDestination.X+=2;
                if (keyboardState.IsKeyDown(Keys.Left))
                    selection.RectangleDestination.X-=2;
                if (keyboardState.IsKeyDown(Keys.Down))
                    selection.RectangleDestination.Y+=2;
                if (keyboardState.IsKeyDown(Keys.Up))
                    selection.RectangleDestination.Y-=2;
            }
            if (keyboardState.IsKeyDown(Keys.Tab))
            {
                if (tangram[selectionné] != null)
                {
                    tangram[selectionné].EstSelectionné = false;
                    depot.Play();
                }
                int i = 0;
                while (i < 7)
                {
                    
                    selectionné = (selectionné + 1) % 7;
                    selection = tangram[selectionné];
                    if (selection != null)
                    {
                        depot.Play();
                        break;
                    }
                    i++;
                }
            }

        } 
        #endregion

        #region Mise à jour
        /// <summary>
        /// Permet au jeu d’exécuter la logique de mise à jour du monde,
        /// de vérifier les collisions, de gérer les entrées et de lire l’audio.
        /// </summary>
        /// <param name="gameTime">Fournit un aperçu des valeurs de temps.</param>
        protected override void Update(GameTime gameTime)
        {
            temps += gameTime.ElapsedGameTime.TotalMilliseconds;
            KeyboardState keyboardState = Keyboard.GetState();
            // Permet au jeu de se fermer
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
                keyboardState.IsKeyDown(Keys.Escape))
                this.Exit();
            if (keyboardState.IsKeyDown(Keys.F11))
                graphics.ToggleFullScreen();
            if (keyboardState.IsKeyDown(Keys.F4))
                MediaPlayer.Volume+=0.01f;
            else if (keyboardState.IsKeyDown(Keys.F3))
                MediaPlayer.Volume -= 0.01f;

            if (keyboardState.IsKeyDown(Keys.F5) && oldKeyboardState.IsKeyUp(Keys.F5))
            {
                tangram.Reinitialisation();
                Initialiser();
            }
            else if (keyboardState.IsKeyDown(Keys.F6) && oldKeyboardState.IsKeyUp(Keys.F6))
            {
                if (partieManger.Partie.MovePrev())
                    Initialiser();
            }
            else if (keyboardState.IsKeyDown(Keys.F7) && oldKeyboardState.IsKeyUp(Keys.F7))
            {
                if (partieManger.Partie.MoveNext())
                    Initialiser();
            }
            if (keyboardState.IsKeyDown(Keys.F8) && oldKeyboardState.IsKeyUp(Keys.F8))
            {
                if (partieManger.Prev())
                {
                    LoadContentPartie();
                    Initialiser();
                }
            }
            else if (keyboardState.IsKeyDown(Keys.F9) && oldKeyboardState.IsKeyUp(Keys.F9))
            {
                if (partieManger.Next())
                {
                    LoadContentPartie();
                    Initialiser();
                }
            }

            
            if (keyboardState.IsKeyDown(Keys.F2) && oldKeyboardState.IsKeyUp(Keys.F2))
                MediaPlayer.IsMuted = !MediaPlayer.IsMuted;
            if (!partieManger.Partie.IsFinish)
            {
                if (!tangram.EstComplete)
                {
                    FormeGeometrique selection = tangram[selectionné];
                    if (cursor.KinectSensor != null)
                        cursor.Update(gameTime);

                    if ((temps - auxtemps) > 20)
                    {
                        if (cursor.KinectSensor != null)
                            ControleKinect(selection);
                        else ControleClavier(selection, keyboardState);
                        auxtemps = temps;
                    }

                    if (selection != null)
                    {
                        for (int i = 0; i < 7; i++)
                        {
                            if (!tangram.FormeOrignes[i].EstVerrouillé && tangram.Placer(selectionné, i,Precision))
                            {
                                selection.EstSelectionné = false;
                                selection = null;
                                selectionné = -1;
                                depot.Play();
                                break;
                            }
                        }
                    }
                    DateTime aux = DateTime.Now;
                    tempsPartie += aux.Subtract(tempsEcouler);
                    tempsEcouler = aux;
                }
                else if ((temps - auxtemps) > 5000)
                {
                    bool partie = partieManger.Partie.Next;
                    if(!partie && partieManger.Next())
                    {
                        LoadContentPartie();
                        partie = true;
                    }
                    if (partie)
                        Initialiser();
                    auxtemps = temps;
                }
            }
            oldKeyboardState = keyboardState;
            base.Update(gameTime);
        }

        private void Initialiser()
        {
            tangram = partieManger.Partie.Tangram;
            tempsEcouler = DateTime.Now;
            tempsPartie = DateTime.Now.Subtract(tempsEcouler);
            isPlaying = false;
        }

        /// <summary>
        /// Appelé quand le jeu doit se dessiner.
        /// </summary>
        /// <param name="gameTime">Fournit un aperçu des valeurs de temps.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(fond, destinationFond, Color.White);
            if (tangram == null)
                return;
            if (tangram.EstComplete)
            {
                spriteBatch.DrawString(spriteFont, "Vous avez gagne : Tangram termine", new Vector2(graphics.PreferredBackBufferWidth / 2 - 200, graphics.PreferredBackBufferHeight / 2), Color.White);
                if(!isPlaying)
                    partieFinie.Play();
                isPlaying = true;
            }
            spriteBatch.DrawString(spriteFont, "Temps  " + tempsPartie.Hours + " : " + tempsPartie.Minutes+" : " + tempsPartie.Seconds+ " Partie : " + partieManger.Partie.Nom + " Tangram : " + tangram.Nom, new Vector2(10, 1), Color.White);
            tangram.Draw(spriteBatch);
            if (cursor.KinectSensor != null)
                cursor.Draw(spriteBatch);
            spriteBatch.End();
            base.Draw(gameTime);
        } 
        #endregion
    }
}
